import normalizeQuery
import c_stemming

def andArticles(l1, l2):
    answer = []
    i = 0
    j = 0
    while True:
        if i >= len(l1):
            return answer 
        elif j >= len(l2):
            return answer
        elif l1[i] == l2[j]:
            answer.append( l1[i] )
            i += 1
            j += 1
        elif l1[i] > l2[j]:
            j += 1
        else:
            i += 1

def orArticles(l1,l2):
    answer = []
    i = 0
    j = 0
    while True:
        if i >= len(l1):
            return answer + l2[j:] 
        elif j >= len(l2):
            return answer + l1[i:]
        elif l1[i] == l2[j]:
            answer.append( l1[i] )
            i += 1
            j += 1
        elif l1[i] > l2[j]:
            if len(answer) == 0 or answer[-1] != l2[j]:
                answer.append( l2[j] )
            j += 1
        else:
            if len(answer) == 0 or  answer[-1] != l1[i]:
                answer.append( l1[i] )            
            i += 1

def test():
    v1 = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    v2 = [3, 6, 9,12, 15, 18, 21, 24, 27, 30]
    print orArticles(v1,v2)
    print andArticles(v1,v2) 
    
def andPositions(lisA, lisB, offset):
    artA = lisA[0]
    artB = lisB[0]
    itArtA = 0
    itArtB = 0
    posA = lisA[1]
    posB = lisB[1]
    itPosA = 0
    itPosB = 0
    
    
    artAns = []
    posAns = []
    
    while True:
        if itArtA >= len( artA ) or itArtB >= len( artB  ) or itPosA >= len ( posA )  or itPosB >= len ( posB ):
            # nie powinno sie wykonac
            return [artAns, posAns]
        if artA[ itArtA  ] == artB[ itArtB ]:
            if abs ( posA[ itPosA ] ) + offset == abs ( posB [ itPosB ] ):
                if len (artAns) == 0 or artA[ itArtA ] != artAns[-1]:
                    artAns.append ( artA[ itArtA ] )
                    posAns.append ( -abs ( posA[ itPosA ] ) )
                else:
                    posAns.append ( abs ( posA[ itPosA ] ) )
        
        if artA[ itArtA ] < artB[ itArtB ]\
            or ( artA [ itArtA ] == artB [ itArtB ]\
            and abs ( posA[ itPosA ] ) + offset < abs ( posB [ itPosB ] ) ):
            
            itPosA = itPosA + 1
            if itPosA >= len( posA ): return [artAns, posAns]
            if posA[ itPosA ] < 0: itArtA = itArtA + 1
        else:
            itPosB = itPosB + 1
            if itPosB >= len( posB ): return [artAns, posAns]
            if posB[ itPosB ] < 0: itArtB = itArtB + 1


def orPositions(lisA, lisB):
    artA = lisA[0]
    artB = lisB[0]
    itArtA = 0
    itArtB = 0
    posA = lisA[1]
    posB = lisB[1]
    itPosA = 0
    itPosB = 0
    
    
    artAns = []
    posAns = []
    
    while True:
        if artA[ itArtA  ] == artB[ itArtB ]\
            and abs ( posA[ itPosA ] )  == abs ( posB [ itPosB ] ):
            
            if len (artAns) == 0 or artA[ itArtA ] != artAns[-1]:
                artAns.append ( artA[ itArtA ] )
                posAns.append ( -abs ( posA[ itPosA ] ) )
            else:
                posAns.append ( abs ( posA[ itPosA ] ) )
            
            itPosA = itPosA + 1
            if itPosA < len( posA ): 
                if posA[ itPosA ] < 0: itArtA = itArtA + 1
            
            itPosB = itPosB + 1
            if itPosB < len( posB ): 
                if posB[ itPosB ] < 0: itArtB = itArtB + 1

        elif artA[ itArtA ] < artB[ itArtB ]\
            or ( artA [ itArtA ] == artB [ itArtB ]\
            and abs ( posA[ itPosA ] )  < abs ( posB [ itPosB ] ) ):
            
            if len (artAns) == 0 or artA[ itArtA ] != artAns[-1]:
                artAns.append ( artA[ itArtA ] )
                posAns.append ( -abs ( posA[ itPosA ] ) )
            else:
                posAns.append ( abs ( posA[ itPosA ] ) )
            
            itPosA = itPosA + 1
            if itPosA < len( posA ): 
                if posA[ itPosA ] < 0: itArtA = itArtA + 1
        else:
            if len (artAns) == 0 or artB[ itArtB ] != artAns[-1]:
                artAns.append ( artB[ itArtB ] )
                posAns.append ( -abs ( posB[ itPosB ] ) )
            else:
                posAns.append ( abs ( posB[ itPosB ] ) )

            itPosB = itPosB + 1
            if itPosB < len( posB ):
                if posB[ itPosB ] < 0: itArtB = itArtB + 1

        if itPosA >= len ( posA ):
            while itPosB < len ( posB ):
                if len (artAns) == 0 or artB[ itArtB ] != artAns[-1]:
                    artAns.append ( artB[ itArtB ] )
                    posAns.append ( -abs ( posB[ itPosB ] ) )
                else:
                    posAns.append ( abs ( posB[ itPosB ] ) )

                itPosB = itPosB + 1
                if itPosB < len( posB ): 
                    if posB[ itPosB ] < 0: 
                        itArtB = itArtB + 1
            return [artAns, posAns]

        if itPosB >= len ( posB ):
            while itPosA < len ( posA ):
                if len (artAns) == 0 or artA[ itArtA ] != artAns[-1]:
                    artAns.append ( artA[ itArtA ] )
                    posAns.append ( -abs ( posA[ itPosA ] ) )
                else:
                    posAns.append ( abs ( posA[ itPosA ] ) )

                itPosA = itPosA + 1
                if itPosA < len( posA ):
                    if posA[ itPosA ] < 0:
                        itArtA = itArtA + 1
            return [artAns, posAns]
    

def orListPositions(l):
    i = 0
    answer = []
    for elem in l:
        if i == 0:
            i = 1
            answer = elem
            continue
        answer = orPositions(answer ,elem)
    assert len(answer) == 2
    return answer
    
def andListPositions(l):
    i = 0
    answer = []
    for elem in l:
        if i == 0:
            i = 1
            answer = elem
            continue
        answer = andPositions(answer ,elem, i)
        i += 1
    assert isinstance(answer,list)
    return answer
    
def orListArticles(l):
    i = 0
    answer = []
    for elem in l:
        if i == 0:
            i = 1
            answer = elem
            continue
        answer = orArticles(answer ,elem)
        assert isinstance(answer,list)
    
    assert isinstance(answer,list)
    return answer
        
def andListArticles(l):
    i = 0
    answer = []
    for elem in l:
        if i == 0:
            i = 1
            answer = elem
            continue
        answer = andArticles(answer ,elem)
    assert isinstance(answer,list)
    return answer
    
def getNumbersForWord(word):
    answer = []
    number = createIndex.getVal(word) - 1

    if number < 804091:
        if len( morfBases[number] ) > 0 :
            return morfBases[number]

    sToken = c_stemming.stemmToken(word) 
    i = -1
    if sToken is not None:
        i = createIndex.getVal(sToken)
    else:
        i = createIndex.getVal(word)
    if i > 0:
        return [i]
    else:
        return []

def getArticlesForWord(word):
    answer = []
    for elem in getNumbersForWord(word):
        answer.append( createIndex.getArticles(elem) )
    assert isinstance(answer,list)
    return orListArticles( answer )
        
def getPositionForWord(word):
    answer = []
    for elem in getNumbersForWord(word):
        answer.append( (createIndex.getArticles(elem),  createIndex.getPositions(elem) )  )
    assert isinstance(answer,list)
    return orListPositions( answer )


def queryPositions(napis):
    napis = normalizeQuery.normalize(napis)
    andQueries = napis.split(" ") 
    answerAnd = []
    for andQuery in andQueries:
        split = andQuery.split("|")
        answerAnd.append( orListPositions( [ getPositionForWord(elem) for elem in split ] ) )

    answer = andListPositions( answerAnd )

    return answer
    
        
def queryArticles(napis):
    napis = normalizeQuery.normalize(napis)
    andQueries = napis.split(" ")
    answerAnd = []
    for andQuery in andQueries:
        split = andQuery.split("|")
        split = [ getArticlesForWord(elem) for elem in split ]
        answerOr = []
        i = 0    
        for elem in split:
            if i == 0:
                i = 1
                answerOr = elem
                continue
            answerOr = orArticles(answerOr, elem)
        answerAnd.append( answerOr )

    answer = []
    i = 0
    for elem in answerAnd:
        if i == 0:
            answer = elem
            i = 1
            continue
        answer = andArticles(answer,elem)
    assert isinstance(answer,list)
    return answer

import time 

start = time.time()
i = 0

pytania = open('pytania_frazowe.txt')
odpowiedzi = open('odpowiedzi_frazowe.txt','w')
for line in pytania:
    i += 1
    lista = queryPositions(line.strip())[0]
    odpowiedzi.write( 'QUERY: ' + line.strip() + ' TOTAL: ' + str(len(lista)) + '\n')
    for elem in lista:
        if 0 < elem - 1< len(titles):
            odpowiedzi.write( titles[elem ].strip() + '\n')
        else:
            odpowiedzi.write( str(elem) + '\n')


end = time.time()
print str( (end - start) / i ) + ' seconds per query'
print str( (end - start) ) + ' seconds total'


start = time.time()
i = 0

pytania = open('pytania_and_dla_IR.txt')
odpowiedzi = open('odpowiedzi_and_dla_IR.txt','w')
for line in pytania:
    #print line.strip()
    i += 1
    lista = queryArticles(line.strip())
    odpowiedzi.write( 'QUERY: ' + line.strip() + ' TOTAL: ' + str(len(lista)) + '\n')
    for elem in lista:
        if 0 < elem - 1< len(titles):
            odpowiedzi.write( titles[elem ].strip() + '\n')
        else:
            odpowiedzi.write( str(elem) + '\n')
        
end = time.time()
print str( (end - start) / i ) + ' seconds per query'
print str( (end - start) ) + ' seconds total'

start = time.time()
i = 0


pytania = open('pytania_or_dla_IR.txt')
odpowiedzi = open('odpowiedzi_or_dla_IR.txt','w')
for line in pytania:
    i += 1
    lista = queryPositions(line.strip())
    odpowiedzi.write( 'QUERY: ' + line.strip() + ' TOTAL: ' + str(len(lista)) + '\n')
    for elem in lista:
        if 0 < elem - 1< len(titles):
            odpowiedzi.write( titles[elem ].strip() + '\n')
        else:
            odpowiedzi.write( str(elem) + '\n')
        

end = time.time()
print str( (end - start) / i ) + ' seconds per query'
print str( (end - start) ) + ' seconds total'
